/**
 * 
 */
package org.heydr.common.util;

import java.io.ByteArrayOutputStream;
import java.io.StringReader;
import java.lang.reflect.Method;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

public class XPathTool {

	private static DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
	private static TransformerFactory transformerFactory = SAXTransformerFactory.newInstance();

	public static String html2XPath(String html, String xslt) {
		if (html == null || "".equals(html) || xslt == null || "".equals(xslt))
			return null;
		String resultInfo = null;
		try {
			if (-1 == html.lastIndexOf("</wml>")) {
				html = html.replace("&nbsp;", " ");
				html = HTMLCleanUtil.clean(html);
				html = html.replaceFirst("<html.*?>", "<html>");
			} else {
				html = html.replaceFirst("<!DOCTYPE.*?>", "");
				html = html.replace("&nbsp;", " ");
			}
			StreamSource xsltStream = new StreamSource(IOUtils.toInputStream(xslt, "utf-8"));
			Transformer transformer = transformerFactory.newTransformer(xsltStream);
			StreamSource xmlStream = new StreamSource(new StringReader(html));
			ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
			transformer.transform(xmlStream, new StreamResult(byteStream));
			resultInfo = byteStream.toString("utf-8");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return resultInfo;
	}
	
	
	public static <T> T extractByXPath(String html, String xslt, T t){
		String xml = html2XPath(html,xslt);
		return extractByDom(xml,t);
	}

	public static <T> T extractByDom(String xml, T t) {
		Document dom = parseXml(xml);
		if (null != dom && null != t) {
			return parseDom(dom, t);
		}
		return null;
	}

	private static Document parseXml(String xml) {
		if (null == xml || "".equals(xml)) {
			return null;
		}
		Document dom = null;
		try {
			DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
			dom = documentBuilder.parse(new InputSource(new StringReader(xml)));
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		return dom;
	}

	private static <T> T parseDom(Document dom, T t) {
		Element root = dom.getDocumentElement();
		NodeList nodeList = root.getChildNodes();
		Class<?> clazz = t.getClass();

		int length = nodeList.getLength();
		for (int i = 0; i < length; i++) {
			Node node = nodeList.item(i);
			String nodeName = node.getNodeName();
			String value = node.getTextContent().trim();
			nodeName = StringUtils.capitalize(nodeName);
			String methodName = "set" + nodeName;
			try {
				Method method = clazz.getMethod(methodName, String.class);
				method.invoke(t, value);
			} catch (Exception e) {
				continue;
			}
		}
		return t;
	}

}
